<script setup lang="ts">
import { ref, watch } from 'vue'
import {
  ElUpload,
  ElIcon,
  ElProgress,
  type UploadInstance,
  UploadRawFile,
  UploadProps
} from 'element-plus'
import { uploadImg } from '@/api/utils/upload'
import { propTypes } from '@/utils/propTypes'
import { Plus } from '@element-plus/icons-vue'
import imageCompression from 'browser-image-compression'
// import { createImageViewer } from '@/components/ImageViewer'

// 定义文件类型和大小限制
const MAX_SIZE_MB = 2
const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/jpg']

/**
 * 此组件为表单中上传单张图片时的需求封装
 * 默认开启进度条动画
 */
const props = defineProps({
  modelValue: propTypes.string.def('')
})
const emit = defineEmits(['update:modelValue'])
const uploadFile = async (options) => {
  const file = options.file

  // 检查文件类型
  if (!ALLOWED_TYPES.includes(file.type)) {
    onError(new Error('仅支持 JPG、PNG、JPEG 格式的图片'))
    return
  }

  // 如果文件大于 2MB，则进行压缩
  if (file.size / 1024 / 1024 > MAX_SIZE_MB) {
    try {
      const compressedFile = await imageCompression(file, {
        maxSizeMB: MAX_SIZE_MB,
        maxWidthOrHeight: 1920, // 可以根据需要调整
        useWebWorker: true
      })

      // 调用上传 API
      return await uploadImg(compressedFile)
    } catch (error) {
      onError(error)
      return
    }
  } else {
    // 调用上传 API
    return await uploadImg(file)
  }
}
const upload = ref<UploadInstance>()
const fileName = ref(props.modelValue)

// 上传成功时的参数拼接以及修改父组件绑定的value值
const onSuccess = (_response: IResponse) => {
  const url = `https://${_response.data.domain}/${_response.data.file_path}`
  emit('update:modelValue', url)
  fileName.value = url
}
const onError = (error) => {
  fileName.value = error
}
// 覆盖前一张图片的处理
const handleExceed: UploadProps['onExceed'] = (files) => {
  upload.value!.clearFiles()
  const file = files[0] as UploadRawFile
  upload.value!.handleStart(file)
  upload.value?.submit()
}
// 预览图片
// const openPreview = () => {
//   if (!props.modelValue) return
//   createImageViewer({
//     urlList: props.modelValue
//   })
// }
// Progress
const showProgress = ref(false)
const progressStatus = ref<any>('')
const percentage = ref(0)
const onChange = (uploadFile) => {
  const percentageNum = {
    ready: 50,
    uploading: 80,
    success: 100,
    fail: 100
  }
  showProgress.value = uploadFile.status !== 'success'
  if (uploadFile.status === 'fail') progressStatus.value = 'exception'
  else progressStatus.value = 'success'
  percentage.value = percentageNum[uploadFile.status]
}
watch(
  () => props.modelValue,
  (newValue) => {
    fileName.value = newValue
  }
)
</script>
<template>
  <ElUpload
    ref="upload"
    :httpRequest="uploadFile"
    :onSuccess="onSuccess"
    :onError="onError"
    :onChange="onChange"
    :onExceed="handleExceed"
    :showFileList="false"
    :limit="1"
    class="avatar-uploader"
  >
    <img v-if="fileName" :src="fileName" class="avatar" />
    <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
    <ElProgress
      :percentage="percentage"
      v-show="showProgress"
      :status="progressStatus"
      :indeterminate="false"
      :show-text="false"
      class="mt-[10px]"
      @click.stop
    />
  </ElUpload>
</template>
<style scoped>
:deep(.el-upload) {
  display: block;
}

.avatar-uploader .avatar {
  display: block;
  width: 178px;
  height: 178px;
}

.avatar-uploader .el-upload {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  width: 178px;
  height: 178px;
  font-size: 28px;
  color: #8c939d;
  text-align: center;
  border: 1px dashed #8c939d;
}
</style>
